package cn.tedu.autoshow.passport.filter;

import cn.tedu.autoshow.commons.constants.HttpConsts;
import cn.tedu.autoshow.commons.pojo.po.LoginInfoPO;
import cn.tedu.autoshow.commons.security.LoginPrincipal;
import cn.tedu.autoshow.commons.util.JwtUtils;
import cn.tedu.autoshow.commons.web.JsonResult;
import cn.tedu.autoshow.commons.web.ServiceCode;
import cn.tedu.autoshow.passport.repository.IAdminJwtRepository;
import com.alibaba.fastjson.JSON;
import io.jsonwebtoken.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collection;
import java.util.List;

@Slf4j
@Component
public class JwtAuthorizationFilter extends OncePerRequestFilter {

    @Value("${autoshow.jwt.secret-key}")
    private String secretKey;
    @Value("${autoshow.jwt.secret-head}")
    private String secretHead;
    @Autowired
    private IAdminJwtRepository adminJwtRepository;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
                                    FilterChain filterChain) throws ServletException, IOException {
        String secretJwt = request.getHeader(HttpConsts.HEADER_AUTHORIZATION);
        log.debug("客户端携带的secretJwt：{}", secretJwt);

        if (StringUtils.hasText(secretJwt) && secretJwt.startsWith(secretHead)) {
            String jwt = secretJwt.substring(secretHead.length());
            //获取jwt中简单登录信息
            LoginInfoPO loginSimpleInfo = JwtUtils.getLoginSimpleInfo(secretKey, jwt);
            if(loginSimpleInfo == null){
                log.debug("jwt解析异常");
                SecurityContextHolder.setContext(SecurityContextHolder.createEmptyContext());
                filterChain.doFilter(request, response);
                return;
            }

            //获取redis中完整登录信息
            LoginInfoPO loginInfo = adminJwtRepository.getLoginInfo(jwt, loginSimpleInfo);

            //检查jwt是否相同
            if (loginInfo != null) {
                log.debug("jwt相同");
            }else {
                log.debug("jwt不同,异地登录");
                SecurityContextHolder.setContext(SecurityContextHolder.createEmptyContext());
                filterChain.doFilter(request, response);
                return;
            }

            //检查是否盗用
            String remoteAddr =  request.getRemoteAddr();
            String userAgent = request.getHeader(HttpConsts.HEADER_USER_AGENT);
            userAgent = userAgent.substring(0,userAgent.indexOf("(")).trim();;
            if (!loginInfo.getRemoteAddr().equals(remoteAddr) &&
                    !loginInfo.getUserAgent().equals(userAgent)) {
                log.warn("JWT可能被盗用，将不向SecurityContext中存入任何认证信息，当前过滤器直接放行");
                SecurityContextHolder.setContext(SecurityContextHolder.createEmptyContext());
                filterChain.doFilter(request, response);
                return;
            }
            response.setContentType("application/json; charset=utf-8");
            //检查是否enabled,检查是否过期,进行续租操作
            if (loginInfo.getEnable() == 1) {
                log.debug("user enabled");
            }else {
                /*log.debug("user not enabled");
                SecurityContextHolder.setContext(SecurityContextHolder.createEmptyContext().);
                filterChain.doFilter(request, response);*/
                JsonResult jsonResult = JsonResult.fail(ServiceCode.ERR_UNAUTHORIZED, "账号已经被禁用");
                String jsonString = JSON.toJSONString(jsonResult);
                PrintWriter printWriter = response.getWriter();
                printWriter.println(jsonString);
                printWriter.close();
                return;
            }

            LoginPrincipal loginPrincipal = new LoginPrincipal();
            loginPrincipal.setId(loginSimpleInfo.getId());
            loginPrincipal.setUsername(loginSimpleInfo.getUsername());

            UsernamePasswordAuthenticationToken authentication =
                    new UsernamePasswordAuthenticationToken(loginPrincipal, null, loginInfo.getAuthorities());
            authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
            SecurityContextHolder.getContext().setAuthentication(authentication);

        }
        filterChain.doFilter(request, response);
    }
}
